﻿using System;
using System.Runtime.Serialization;

namespace IntoNails.Models
{
    public enum UserType
    {
        NormalUser,
        Staff,
        Receipt,
        Technical,
        Admin
    }

    public enum GenderType
    {
        Other,
        Male,
        Female
    }

	/// <summary>
	/// Description of User.
	/// </summary>
	[Serializable]
    public class User : AbstractModel<Guid>, ISerializable
    {
        #region Fields

	    private string _username;
	    private string _password;

	    private string _firstName;
        private string _middleName;
        private string _lastName;
	    private UserType _authority;
        private GenderType _gender;

        private string _address;
        private string _city;
        private string _state;
        private string _zip;

	    private DateTime _dateOfBirth;
	    private DateTime _hireDate;

	    private string _contactNumber;
	    private string _cellPhone;
	    private string _email;

	    private string _ssn;
	    private string _contractNumber;

	    private string _comment;

        #endregion

        #region Constructors

        protected User()
        {
        }

        public User(SerializationInfo info, StreamingContext context)
        {
            this.UniqueCode = (Guid) info.GetValue("UniqueCode", typeof (Guid));

            #region Login Info

            this.Username = info.GetString("Username");
            this.Password = info.GetString("Password");

            #endregion

            #region General

            this.FirstName = info.GetString("FirstName");
            this.MiddleName = info.GetString("MiddleName");
            this.LastName = info.GetString("LastName");

            this.Authority = (UserType) info.GetValue("Authority", typeof (UserType));
            this.Gender = (GenderType) info.GetValue("Gender", typeof (GenderType));

            #endregion

            #region Address

            this.Address = info.GetString("Address");
            this.City = info.GetString("City");
            this.State = info.GetString("State");
            this.Zip = info.GetString("Zip");

            #endregion

            #region Dates

            this.DateOfBirth = info.GetDateTime("DateOfBirth");
            this.HireDate = info.GetDateTime("HireDate");
            this.CreatedDate = info.GetDateTime("CreatedDate");
            this.UpdatedDate = info.GetDateTime("UpdatedDate");

            #endregion

            #region Contacts

            this.ContactNumber = info.GetString("ContactNumber");
            this.CellPhoneNumber = info.GetString("CellPhoneNumber");
            this.Email = info.GetString("Email");

            #endregion

            #region Reference Numbers

            this.SSN = info.GetString("SSN");
            this.ContractorNumber = info.GetString("ContractorNumber");

            #endregion

            #region Other

            this.Comment = info.GetString("Comment");
            this.IsValid = info.GetBoolean("IsValid");

            #endregion
        }

	    #endregion

        #region Properties
        
        #region Login Info

	    public string Username
	    {
	        get { return this._username; }
	        set
	        {
	            this._username = value;
	            base.RaisePropertyChanged("Username");
	        }
	    }

	    public string Password
	    {
	        get { return this._password; }
	        set
	        {
	            this._password = value;
	            base.RaisePropertyChanged("Password");
	        }
	    }

	    #endregion

        #region General

        public string FirstName
        {
            get { return this._firstName; }
            set
            {
                this._firstName = value;
                base.RaisePropertyChanged("FirstName");
            }
        }

	    public string MiddleName
	    {
	        get { return this._middleName; }
	        set
	        {
	            this._middleName = value;
	            base.RaisePropertyChanged("MiddleName");
	        }
	    }

	    public string LastName
	    {
	        get { return this._lastName; }
	        set
	        {
	            this._lastName = value;
	            base.RaisePropertyChanged("LastName");
	        }
	    }

	    public UserType Authority
	    {
	        get { return this._authority; }
	        set
	        {
	            this._authority = value;
	            base.RaisePropertyChanged("Authority");
	        }
	    }

	    public GenderType Gender
	    {
	        get { return this._gender; }
	        set
	        {
	            this._gender = value;
	            base.RaisePropertyChanged("Gender");
	        }
	    }

	    #endregion

        #region Address

	    public string Address
	    {
	        get { return this._address; }
	        set
	        {
	            this._address = value;
	            base.RaisePropertyChanged("Address");
	        }
	    }

	    public string City
	    {
	        get { return this._city; }
	        set
	        {
	            this._city = value;
	            base.RaisePropertyChanged("City");
	        }
	    }

	    public string State
	    {
	        get { return this._state; }
	        set
	        {
	            this._state = value;
	            base.RaisePropertyChanged("State");
	        }
	    }

	    public string Zip
        {
            get { return this._zip; }
            set
            {
                this._zip = value;
                base.RaisePropertyChanged("Zip");
            }
        }

        #endregion

        #region Dates

	    public DateTime DateOfBirth
	    {
	        get { return this._dateOfBirth; }
	        set
	        {
	            this._dateOfBirth = value;
	            base.RaisePropertyChanged("DateOfBirth");
	        }
	    }

	    public DateTime HireDate
	    {
	        get { return this._hireDate; }
	        set
	        {
	            this._hireDate = value;
	            base.RaisePropertyChanged("HireDate");
	        }
	    }

	    #endregion

        #region Contacts

	    public string ContactNumber
	    {
	        get { return this._contactNumber; }
	        set
	        {
	            this._contactNumber = value;
	            base.RaisePropertyChanged("ContactNumber");
	        }
	    }

	    public string CellPhoneNumber
	    {
	        get { return this._cellPhone; }
	        set
	        {
	            this._cellPhone = value;
	            base.RaisePropertyChanged("CellPhoneNumber");
	        }
	    }

	    public string Email
        {
            get { return this._email; }
            set
            {
                this._email = value;
                base.RaisePropertyChanged("Email");
            }
        }

        #endregion

        #region Reference Numbers

	    public string SSN
	    {
	        get { return this._ssn; }
	        set
	        {
	            this._ssn = value;
	            base.RaisePropertyChanged("SSN");
	        }
	    }

	    public string ContractorNumber
	    {
	        get { return this._contractNumber; }
	        set
	        {
	            this._contractNumber = value;
	            base.RaisePropertyChanged("ContractorNumber");
	        }
	    }

	    #endregion

        #region Other

	    public string Comment
	    {
	        get { return this._comment; }
	        set
	        {
	            this._comment = value;
	            base.RaisePropertyChanged("Comment");
	        }
	    }

	    #endregion

        #endregion

        public static User CreateAdmin()
        {
            return new User()
            {
                UniqueCode = Guid.NewGuid(),
                Authority = UserType.Admin,
                HireDate = DateTime.Now,
                CreatedDate = DateTime.Now,
                UpdatedDate = DateTime.Now,
                IsValid = true
            };
        }

        public static User CreateNewUser()
        {
            return new User()
                       {
                           UniqueCode = Guid.NewGuid(),
                           Authority = UserType.NormalUser,
                           HireDate = DateTime.Now,
                           CreatedDate = DateTime.Now,
                           UpdatedDate = DateTime.Now,
                           IsValid = true
                       };
        }

	    #region Implementation of ISerializable

	    public void GetObjectData(SerializationInfo info, StreamingContext context)
	    {
            info.AddValue("UniqueCode", this.UniqueCode);

            #region Login Info

            info.AddValue("Username", this.Username);
            info.AddValue("Password", this.Password);

            #endregion

            #region General

            info.AddValue("FirstName", this.FirstName);
            info.AddValue("MiddleName", this.MiddleName);
            info.AddValue("LastName", this.LastName);

            info.AddValue("Authority", this.Authority);
            info.AddValue("Gender", this.Gender);

            #endregion

            #region Address

            info.AddValue("Address", this.Address);
            info.AddValue("City", this.City);
            info.AddValue("State", this.State);
            info.AddValue("Zip", this.Zip);

            #endregion

            #region Dates

            info.AddValue("DateOfBirth", this.DateOfBirth);
            info.AddValue("HireDate", this.HireDate);
            info.AddValue("CreatedDate", this.CreatedDate);
            info.AddValue("UpdatedDate", this.UpdatedDate);

            #endregion

            #region Contacts

            info.AddValue("ContactNumber", this.ContactNumber);
            info.AddValue("CellPhoneNumber", this.CellPhoneNumber);
            info.AddValue("Email", this.Email);

            #endregion

            #region Reference Numbers

            info.AddValue("SSN", this.SSN);
            info.AddValue("ContractorNumber", this.ContractorNumber);

            #endregion

            #region Other

            info.AddValue("Comment", this.Comment);
            info.AddValue("IsValid", this.IsValid);

            #endregion
	    }

	    #endregion

        #region Object Overriden

        public override string ToString()
        {
            return string.Format("ID: {0} | Full-Name: {1} {2} {3}", this.UniqueCode, this.FirstName, this.MiddleName, this.LastName);
        }

        public override int GetHashCode()
        {
            int hashCode = 0;

            unchecked
            {
                hashCode += this.UniqueCode.GetHashCode();
                ////hashCode += !string.IsNullOrEmpty(this.DisplayName) ? this.DisplayName.GetHashCode() : 0;

                ////hashCode += !string.IsNullOrEmpty(this.FirstName) ? this.FirstName.GetHashCode() : 0;
                ////hashCode += !string.IsNullOrEmpty(this.MiddleName) ? this.MiddleName.GetHashCode() : 0;
                ////hashCode += !string.IsNullOrEmpty(this.LastName) ? this.LastName.GetHashCode() : 0;
                ////hashCode += this.Authority.GetHashCode();
                ////hashCode += this.Gender.GetHashCode();

                ////hashCode += !string.IsNullOrEmpty(this.Username) ? this.Username.GetHashCode() : 0;
                ////hashCode += !string.IsNullOrEmpty(this.Password) ? this.Password.GetHashCode() : 0;

                ////hashCode += this.Address.GetHashCode();
                ////hashCode += this.City.GetHashCode();
                ////hashCode += this.State.GetHashCode();
                ////hashCode += this.Zip.GetHashCode();

                ////hashCode += this.DateOfBirth.GetHashCode();
                ////hashCode += this.HireDate.GetHashCode();

                ////hashCode += this.ContactNumber.GetHashCode();
                ////hashCode += this.CellPhoneNumber.GetHashCode();
                ////hashCode += this.Email.GetHashCode();

                ////hashCode += this.SSN.GetHashCode();
                ////hashCode += this.ContractorNumber.GetHashCode();

                ////hashCode += this.Comment.GetHashCode();

                ////hashCode += this.CreatedDate.GetHashCode();
                ////hashCode += this.UpdatedDate.GetHashCode();
                ////hashCode += this.IsValid.GetHashCode();
            }

            return hashCode;
        }

        public override bool Equals(object obj)
        {
            User other = obj as User;
            if (other == null)
            {
                return false;
            }

            return this.UniqueCode == other.UniqueCode;
        }

        #endregion
	}
}
